package pers.mihao.quickstream.common.model;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.util.*;

@Data
public class Features implements Serializable {
    private static final long serialVersionUID = 7016995565096563857L;

    private Map<String, String> featuresMap;

    private Map<String, String> featuresToUpdate;
    private Set<String> featuresToDelete;

    public Features() {
        this(new HashMap<>());
    }

    public Features(Map<String, String> featuresMap) {
        if (featuresMap == null) {
            this.featuresMap = new HashMap<>(0);
        } else {
            this.featuresMap = new HashMap<>(featuresMap);
        }
        this.featuresToUpdate = new HashMap<>();
        this.featuresToDelete = new HashSet<>();
    }

    public Features(Features features) {
        this(features != null ? features.getFeaturesMap() : new HashMap<>(0));
    }

    public void update(String key, String value) {
        if (StringUtils.isBlank(key)) {
            return;
        }
        featuresToUpdate.put(key, value);

        featuresMap.put(key, value);
        featuresToDelete.remove(key);
    }

    public void remove(String key) {
        if (StringUtils.isBlank(key)) {
            return;
        }
        featuresToDelete.add(key);

        featuresToUpdate.remove(key);
        featuresMap.remove(key);
    }

    public String read(String key) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        return featuresMap.get(key);
    }

    public Boolean readBoolean(String key) {
        String value = read(key);
        if (value == null) {
            return null;
        }
        return Boolean.parseBoolean(value);
    }

    public Long readLong(String key) {
        String value = read(key);
        if (value == null) {
            return null;
        }
        return Long.parseLong(value);
    }

    public Integer readIntOrDefault(String key, Integer defaultValue) {
        return Optional.ofNullable(readInt(key)).orElse(defaultValue);
    }

    public Integer readInt(String key) {
        String value = read(key);
        if (value == null) {
            return null;
        }
        return Integer.parseInt(value);
    }

    public List<String> readStrList(String key) {
        String value = read(key);
        if (value == null) {
            return null;
        }
        return JSON.parseObject(value, new TypeReference<List<String>>() {
        });
    }

    public List<Long> readLongList(String key) {
        String value = read(key);
        if (value == null) {
            return null;
        }
        return JSON.parseObject(value, new TypeReference<List<Long>>() {
        });
    }

    /**
     * 更新 features 使用 {@link #update(String, String)} ，不使用该方法
     */
    public Map<String, String> featuresToUpdate() {
        return new HashMap<>(this.featuresToUpdate);
    }

    /**
     * 删除 features 使用 {@link #remove(String)} ，不使用该方法
     */
    public Set<String> featuresToDelete() {
        return new HashSet<>(this.featuresToDelete);
    }

    public Map<String, String> readAll() {
        return new HashMap<>(featuresMap);
    }

    public boolean modified() {
        return !noModified();
    }

    public boolean noModified() {
        return featuresToDelete.isEmpty()
                && featuresToUpdate.isEmpty();
    }
}
